// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#pragma once

#include <pollux/testing/expression/fuzzer_toolkit.h>

namespace kumo::pollux::fuzzer {

class JsonParseArgValuesGenerator : public ArgValuesGenerator {
 public:
  ~JsonParseArgValuesGenerator() override = default;

  std::vector<core::TypedExprPtr> generate(
      const CallableSignature& signature,
      const VectorFuzzer::Options& options,
      FuzzerGenerator& rng,
      ExpressionFuzzerState& state) override;
};

class StringEscapeArgValuesGenerator : public ArgValuesGenerator {
 public:
  ~StringEscapeArgValuesGenerator() override = default;

  std::vector<core::TypedExprPtr> generate(
      const CallableSignature& signature,
      const VectorFuzzer::Options& options,
      FuzzerGenerator& rng,
      ExpressionFuzzerState& state) override;
};

class PhoneNumberArgValuesGenerator : public ArgValuesGenerator {
 public:
  explicit PhoneNumberArgValuesGenerator(std::string functionName) {
    functionName_ = std::move(functionName);
  }
  ~PhoneNumberArgValuesGenerator() override = default;

  std::vector<core::TypedExprPtr> generate(
      const CallableSignature& signature,
      const VectorFuzzer::Options& options,
      FuzzerGenerator& rng,
      ExpressionFuzzerState& state) override;

 private:
  std::string functionName_;
};

// This input generator randomly choose a data type that the JSON argument
// represents, and use the JsonInputGenerator and JsonPathGenerator to generate
// the values for this type. When generating the JSON and JSON-path argument, it
// makes the following two assumptions:
// 2. the size of all container types in the JSON argument do not exceed a
// randomly generated maxContainerSize.
// 1. either all map keys in all maps in the JSON argument are VARCHAR or they
// are BIGINT, and all map-key values are choosen from a randomly generated
// candidate set. The size of the candidate map-key set is slightly larger than
// maxContainerSize, so that access into maps by keys has matches and misses.
//
// 10% of times makes a random variation to both the JSON argument and JSON-path
// argument to test invalid cases.
class JsonExtractArgValuesGenerator : public ArgValuesGenerator {
 public:
  ~JsonExtractArgValuesGenerator() override = default;

  std::vector<core::TypedExprPtr> generate(
      const CallableSignature& signature,
      const VectorFuzzer::Options& options,
      FuzzerGenerator& rng,
      ExpressionFuzzerState& state) override;
};

} // namespace kumo::pollux::fuzzer
